#include <iostream>
#include <string>
#include "AnimationWriter.h"
#include "HairCore.h"

using namespace std;
using namespace Eigen;
using namespace XRwy;

int main(int argc, char* argv[]) {
	using namespace std;
	using namespace XRwy;

	const string file_path = "/Volumes/Storage/Developer/project/Hair Simulation/Data/Hair/straight-125.hair";
	const string head_trans_file_path = "/Volumes/Storage/Developer/project/Hair Simulation/Data/Model/Model 2/Motions/static/head_trans.txt";
    const string sdf_world2local_file_path = "/Volumes/Storage/Developer/project/Hair Simulation/Data/Model/Model 2/Motions/static/collider_world2local.txt";
	const string anim_file_path = "/Users/vivi/Desktop/test.anim";

	const HairReader reader(file_path, 0.01, MIRROR_Y, 2000); //only select one hair strand
	const TransformationReader head_trans_matrix_reader(head_trans_file_path);
    const TransformationReader sdf_world2local_matrix_reader(sdf_world2local_file_path);

	SDFObject sdf(
			R"(/Volumes/Storage/Developer/project/Hair Simulation/Data/Model/Model 2/Collision/head2.sdf)", //sdf path
			sdf_world2local_matrix_reader.get_trans(0), //world2local
			0.005f, //collision_tolerance
			0.03f / 15 //impulse_time
	);

	Vector3f gravity_acc;
	gravity_acc << 0.0f, -9.8f, 0.0f;

	HairSimulatorConfDict conf_dict;
	conf_dict["enable_body_collision"] = "true";
	conf_dict["enable_hair_stiction"] = "false";
	conf_dict["enable_npass"] = "true";
	conf_dict["npass"] = "100";

	conf_dict["k"] = "1000000";
	conf_dict["air_damping"] = "5";
	conf_dict["damping"] = "0";
	conf_dict["acc_x"] = "0.0";
	conf_dict["acc_y"] = "-9.8";
	conf_dict["acc_z"] = "0.0";

	conf_dict["stiction_type"] = "cage";

	conf_dict["cage_stiction_rate"] = "0.02";

	conf_dict["density_stiction_rate"] = "0";
	conf_dict["density_cell_count"] = "8";

	conf_dict["spring_distance"] = "0.01";
	conf_dict["spring_tolerance"] = "1.7";
	conf_dict["spring_acc"] = "6.5";

	//for reduced interpolation hair model
	conf_dict["weights_file_path"] = "/Users/vivi/Developer/project/Hair Simulation/Data/Reduced/04-29/rand-04-29 13h47m37s-weights.weights2";

	const HairSelleSimulatorConfiguration conf(conf_dict);
	HairAcceleratedSelleSimulator simulator(reader, conf);
//	const HairInterpolationSimulatorConfiguration conf(conf_dict);
//	HairInterpolationSimulator simulator(reader, conf);

	vector<int> strand_particle_count;
	for (size_t i = 0; i < simulator.get_strand_count(); ++i)
		strand_particle_count.push_back(simulator.get_particle_count_on_strand(i));

	AnimationWriter writer(anim_file_path, strand_particle_count);

	float *positions = new float[simulator.get_particle_count() * 3];
	float transformation[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};

    simulator.copy_particles(positions);
    writer.feed(transformation, positions);

    int total_frame_count = min(head_trans_matrix_reader.size(), sdf_world2local_matrix_reader.size());
	cout << "Total executing frame count: " << total_frame_count << endl;
	for (int i = 1; i < total_frame_count; ++i) {
		cout << i << endl;

		HairSimulatorData data{
                head_trans_matrix_reader.get_trans(i),
                0.03f,
                &sdf,
                sdf_world2local_matrix_reader.get_trans(i)
        };
		for (int j = 0; j < 4; ++j)
			for (int k = 0; k < 4; ++k)
				transformation[j * 4 + k] = data.motion_transform(j, k);

		simulator.on_frame(data);
		simulator.copy_particles(positions);
		writer.feed(transformation, positions);
	}
}
